#include <iostream>
using namespace std;

template <typename T>
class SingleLinkedList
{
private:
    class Node
    {
    private:
	T data;
	Node* next = NULL;
	Node(){};
	~Node(){};
    public:
	friend class SingleLinkedList<T>;
    };
    Node* head = NULL;
    Node EMPTY;
    T error(int _err) const;
public:
    SingleLinkedList(){};
    ~SingleLinkedList();
    void push(const T& _d);
    const T& top() const;
    T pop();
    void print() const;
    T del(int _i);
    T ins(int _i, T _a);
    int len() const;
};
template <typename T>
int SingleLinkedList<T>::len() const
{
    Node* r = head;
    int j = 1;
    while (r->next)
    {
	r = r->next;
	j++;
    }
    return j;
}
template <typename T>
T SingleLinkedList<T>::ins(int _i, T _a)
{
    Node* p = head;
    int j = 1;
    while (p && j < _i - 1)
    {
	p = p->next;
	++j;
    }
    if (!p || _i < 1)
	error(2);
    else if (j == 1)
	push(_a);
    else
    {
	Node* t = new Node;
	t->data = _a;
	t->next = p->next;
	p->next = t;
	return _a;
    }
}
	
    
	
template <typename T>
T SingleLinkedList<T>::del(int _i)
{
    Node* p = head;
    int j = 1;
    while (p->next && j < _i - 1)
    {
	p = p->next;
	++j;
    }
    if (!p->next || _i < 1)
	error(2);
    else if (j == 1)
	pop();
    else
    {
	Node* q = p->next;
	T val = q->data;
	p->next = q->next;
	delete q;
	return val;
    }
}
template <typename T>
SingleLinkedList<T>::~SingleLinkedList()
{
    while (head != NULL)
    {
	Node* t = head;
	head = head->next;
	delete t;
    }
}

template <typename T>
T SingleLinkedList<T>::error(int _err) const
{
    switch (_err)
    {
    case 1:
	cerr << "This list is empty!" << endl;
        return EMPTY.data;
	break;
    case 2:
	cerr << "the location is not reasonable" << endl;
	return EMPTY.data;
	break;
    default:
	break;
    }
}

template <typename T>
T SingleLinkedList<T>::pop()
{
    if (head == NULL)
	error(1);
    else
    {
	T result;
	Node* t = head;
	result = t->data;
	head = head->next;
	delete t;
	return result;
    }	 
}

template <typename T>
const T& SingleLinkedList<T>::top() const
{
    if (head == NULL)
	error(1);
    return head->data;	
}

template <typename T>
void SingleLinkedList<T>::print() const
{
    Node* t = head;
    while (t != NULL)
    {
	cout << t->data << ", ";
	t = t->next;
    }
    cout << "\b\b" << endl;
}

template <typename T>
void SingleLinkedList<T>::push(const T& _d)
{
    Node* t = new Node;
    t->data = _d;
    t->next = head;
    head = t;
}

int main()
{
    SingleLinkedList<int> a;
    for (int i = 0; i < 10; i++)
	a.push(i * i);
    cout << a.top() << endl;
    a.print();
    cout << a.del(5) << endl;
    a.print();
    cout << a.ins(10, 25) << endl;
    a.print();
    int n = a.len();
    for (int i = 0; i < n; i++)
        cout << a.pop() << ", ";
    cout << "\b\b" << endl;
    return 0;
}
